﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;

namespace ParsingProject {

    /// <summary>
    /// Model for creature that moves.
    /// <list type="bullet">
    /// <item>
    /// <term>Authors:</term>
    /// <description>David I. Schwartz</description>
    /// <description>Sela Davis</description>
    /// </item>
    /// </list>
    /// </summary>
    public class Creature {

        #region fields
        //---Orientation----------------------------------------------------------------
        /// <summary>
        /// An enum representing the cardinal directions.
        /// </summary>
        public enum DIRECTION {
            NORTH, EAST, SOUTH, WEST
        };

        // default direction:
        private DIRECTION orientation = DIRECTION.NORTH;

        /// <summary>
        /// Access orientation (NORTH, EAST, SOUTH, or WEST).
        /// </summary>
        public DIRECTION Orientation {
            get { return orientation; }
            set { orientation = value; }
        }

        //---Location--------------------------------------------------------------------
        private int x;                    // horizontal locaiton
        private int y;                    // vertical location

        /// <summary>
        /// Access horizontal position.
        /// </summary>
        public int X {
            get { return x; }
            set { x = value; }
        }

        /// <summary>
        /// Access verticle position.
        /// </summary>
        public int Y {
            get { return y; }
            set { y = value; }
        }

        //---Motion----------------------------------------------------------------------
        public const int GO_VALUE = 1;    // how much "go" moves
        public const int JUMP_VALUE = 2;  // how much "jump" moves
        public const int TURN_VALUE = 90; // how much "turn" moves
        public const int PAUSE_VALUE = 0; // how much "pause" moves

        //---Parsing of creature commands------------------------------------------------
        private char[] separators = null; // whitespace


        //Zachary Behrmann & Rob Husfeldt
        private PictureBox boxxy;
        private string strMe;
        private bool skip = false;
        private bool check = true;
        /*
        private Queue<MotionPair> moves;   // sequence of actions and amounts parsed from expression
        */
        #endregion fields

        #region constructors

        public PictureBox Boxxy
        {
            get { return boxxy; }
            set { boxxy = value; }
        }

        public string StringMe
        {
            get { return strMe; }
            set { strMe = value; }
        }
        /*
        public Queue<MotionPair> Moves
        {
            get { return moves; }
            set { moves = value; }
        }
        */

        /// <summary>
        /// Make a new creature.
        /// </summary>
        /// <param name="x">horizontal position</param>
        /// <param name="y">vertical position</param>
        public Creature(int x, int y, string me) {
            this.x = x;
            this.y = y;
            strMe = me;
        }

        /// <summary>
        /// Make a defaul creature. Location: (0,0).
        /// </summary>
        public Creature() {
            x = 0;
            y = 0;
        }

        #endregion constructors

        #region parsing

        /// <summary>
        /// Parse input for correct syntax and updating the
        /// motion that the animation needs to do.
        /// </summary>
        /// <param name="expresssion">a "sentence" of text to parse</param>
        /// <returns>a queue that stores the sequence of moves and amounts for creature</returns>
        public Queue<MotionPair> interpretCommand(string expresssion) {
            Queue<MotionPair> q = new Queue<MotionPair>(0);
            Tokenizer tkn = new Tokenizer(expresssion,separators);
            check = true;
            parseExp(expresssion, tkn, q);
            return q;
        }

        /*
        public void interprept(string expression)
        {
            Queue<MotionPair> q = new Queue<MotionPair>(0);
            Tokenizer tkn = new Tokenizer(expression, separators);
            parseExp(expression, tkn, q);

        }
        */
        //Zachary Behrmann & Rob Husfeldt
        /// <summary>
        /// Parses the expression word by word recursively.
        /// <br>Syntax:
        /// <br>S -> P .
        /// <br>P -> P and P
        /// <br>P -> N V
        /// <br>N -> "I"
        /// <br>V -> "go"
        /// <br>V -> "jump"
        /// <br>V -> "pause"
        /// V -> "die"
        /// v -> "flee"
        /// v -> "spin"
        /// v -> "thrust"
        /// v -> "spin"
        //
        /// <br>Semantics:
        /// <br>move moves 1, jump moves 2, pause moves 0, turn rotates 90 deg clockwise
        /// </summary>
        private void parseExp(string exp, Tokenizer tkn, Queue<MotionPair> moves) {

            // get next token from tokenizer and parse it:
            //string current = tkn.nextToken();
            //string next = tkn.peekToken();
            string current = tkn.peekToken();
            string next = tkn.nextToken();

            if (check)
            {
                if (strMe == next || next == "We")
                    skip = false;
                else
                    skip = true;

                check = false;
            }
            else
            {
                if (!skip)
                {

                    switch (next)
                    {
                        case "go":
                        case "goes":
                            moves.Enqueue(new MotionPair("move", 1));
                            break;
                        case "jump":
                        case "jumps":
                            moves.Enqueue(new MotionPair("move", 2));
                            break;
                        case "turn":
                        case "turns":
                            moves.Enqueue(new MotionPair("turn", 90));
                            break;
                        case "and":
                            check = true;
                            break;
                        case "flee":
                        case "flees":
                            moves.Enqueue(new MotionPair("turn", 180));
                            moves.Enqueue(new MotionPair("move", 2));
                            break;
                        default:
                            moves.Enqueue(new MotionPair("broken", -1));
                            break;
                        case "die":
                        case "dies":
                            moves.Enqueue(new MotionPair("die", -1));
                            break;
                        case "spin":
                        case "spins":
                            moves.Enqueue(new MotionPair("turn", 360));
                            break;
                        case "thrust":
                        case "thrusts":
                            moves.Enqueue(new MotionPair("move",3));
                            break;
                        case "roll":
                        case "rolls":
                            moves.Enqueue(new MotionPair("roll", 0));
                            break;
                    }
                }
                else
                    skip = false;
            }
            /*
             * COMPLETE ME
             * 
             */

            // keep parsing if we haven't terminated the expression:
            if (tkn.peekToken() != ".") 
                parseExp(exp, tkn, moves);

        } // method parseExp

        #endregion parsing

    } // class Creature

} // namespace ParsingProject
